// ignore_for_file: avoid_print

import 'dart:io';

import 'package:native_assets_cli/native_assets_cli.dart';
import 'package:http/http.dart' as http;

const xmakePlatformMapping = {
  "linux": "linux",
  "macos": "macosx",
  "windows": "mingw",
  "android": "android",
  "ios": "iphoneos"
  // fuchsia, xcode not support!
};
const dynamicLibPostfixMapping = {
  'android': 'so',
  'linux': 'so',
  'ios': 'dylib',
  'macos': 'dylib',
  'windows': 'dll',
  'mingw': 'dll',
};
// native_assets_cli/lib/src/model/os.dart: OSImpl
const abiMapping = {
  'android': {
    'arm': 'armeabi-v7a',
    'arm64': 'arm64-v8a',
    'ia32': 'x86_64',
    'x64': 'x86_64',
    'riscv64': ''
  },
  'ios': {'arm': 'armv7', 'arm64': 'arm64', 'x64': 'x86_64'},
  'linux': {
    'arm': 'arm64',
    'arm64': 'arm64',
    'ia32': 'x86_64',
    'x64': 'x86_64',
    'riscv32': '',
    'riscv64': ''
  },
  'macos': {'arm64': 'arm64', 'x64': 'x86_64'},
  'windows': {'arm64': '', 'ia32': 'x86_64', 'x64': 'x86_64'}
};
void main(List<String> args) async {
  await build(args, (config, output) async {
    final String targetOs = config.targetOS.toString();
    final String arch = config.targetArchitecture.toString();

    String assetName = 'libqjs.${dynamicLibPostfixMapping[targetOs]}';
    Uri assetSourcePath = config.packageRoot.resolveUri(Uri.file(
        'qjs/${xmakePlatformMapping[targetOs]}/${abiMapping[targetOs]![arch]}/release/lib/$assetName'));
    Uri assetPath = config.outputDirectory.resolve(assetName);
    print(
        'dir.current: ${Directory.current.absolute.path}, targetOs: $targetOs, arch: $arch, destFile: $assetPath');

    // bundle to deps
    if (!config.dryRun) {
      await File.fromUri(assetSourcePath).copy(assetPath.toFilePath());
      // await downloadAsset(assetSourcePath.path, assetPath);
      output.addDependencies(
          [assetSourcePath, config.packageRoot.resolve('hook/build.dart')]);
    }
    // NativeCodeAsset.file lookup symbol from bundle file.
    output.addAsset(NativeCodeAsset(
        package: config.packageName,
        name: 'qjs/binding/quickjs.dart',
        linkMode: DynamicLoadingBundled(),
        os: config.targetOS,
        architecture: config.targetArchitecture,
        file: assetPath));
  });
}

Future<void> addAssetsDeps(BuildConfig config, BuildOutput output) async {
  final packageName = config.packageName;
  final assetDirectory =
      Directory.fromUri(config.packageRoot.resolve('assets/'));
  output.addDependency(assetDirectory.uri);

  await for (final dataAsset in assetDirectory.list()) {
    if (dataAsset is! File) {
      continue;
    }

    // add dependency.
    final name = dataAsset.uri
        .toFilePath(windows: false)
        .substring(config.packageRoot.toFilePath(windows: false).length);
    output.addAsset(
        DataAsset(package: packageName, name: name, file: dataAsset.uri),
        linkInPackage: config.linkingEnabled ? packageName : null);
    output.addDependency(dataAsset.uri);
  }
}

Future<void> downloadAsset(String assetUrl, Uri destinationFile) async {
  final downloadUri = Uri.parse(assetUrl);
  final downloadedFile = File(destinationFile.toFilePath());
  print('Saving file to  ${downloadedFile.absolute.path}');

  final downloadResponse = await http.get(downloadUri);
  print('Download response: ${downloadResponse.statusCode}');

  if (downloadResponse.statusCode == 200) {
    if (downloadedFile.existsSync()) {
      downloadedFile.deleteSync();
    }
    downloadedFile.createSync();
    print('Saved file to ${downloadedFile.absolute.path}\n');
    downloadedFile.writeAsBytes(downloadResponse.bodyBytes);
  } else {
    print(
        '${downloadResponse.statusCode} :: ${downloadResponse.body} $assetUrl');
    throw Exception(
        '${downloadResponse.statusCode} :: ${downloadResponse.body} $assetUrl');
  }
}
